package com.huawei.esdk.tpoa.business.oa.sitemgr;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import com.huawei.esdk.platform.common.SDKErrorCode;
import com.huawei.esdk.platform.common.SDKResult;
import com.huawei.esdk.platform.common.config.ConfigManager;
import com.huawei.esdk.platform.common.exception.SDKException;
import com.huawei.esdk.platform.common.utils.DateUtils;
import com.huawei.esdk.platform.common.utils.DurationUtils;
import com.huawei.esdk.platform.common.utils.StringUtils;
import com.huawei.esdk.tp.domain.model.Conference;
import com.huawei.esdk.tp.domain.model.ScheduleConference;
import com.huawei.esdk.tp.domain.model.Site;
import com.huawei.esdk.tp.domain.model.SiteInConference;
import com.huawei.esdk.tp.domain.model.bean.ConfStatus;
import com.huawei.esdk.tp.domain.model.bean.FreeBusyInfo;
import com.huawei.esdk.tpoa.business.oa.convert.TPOAConfMgrConvert;
import com.huawei.esdk.tpoa.business.oa.mapping.TPOADataMapping;

public class TPOASiteSynchronizationHandler
{   
    //30秒之前的SMC上的会议列表
    private Map<String, Conference> confListMap_before = new HashMap<String, Conference>();
    
    //当前SMC上的会议列表
    private Map<String, Conference> confListMap_now = new HashMap<String, Conference>();
    
    //需要向exchange上添加的会议
    private Map<String, Conference> changed_confList_add = new HashMap<String, Conference>();
    
    //需要在exchange上删除的会议
    private Map<String, Conference> changed_confList_delete = new HashMap<String, Conference>();
    
    //需要在exchange上修改的会议
    private Map<String, Conference> changed_confList_modify = new HashMap<String, Conference>();
    
    //转换类，通过TPOA映射类，把TP 会议的数据 转化为 exchange上的会议数据
    private TPOAConfMgrConvert tpoaConfMgrConvert = new TPOAConfMgrConvert();
    
    //预约会议的领域类
    private ScheduleConference scheduleConf = new ScheduleConference();
    
    //日志类
    private static final Logger LOGGER = Logger.getLogger(TPOASiteSynchronizationHandler.class);
    
    //用于存放周期会议的主会议Id
    Map<String, String> recurrenceConfParentIds = new HashMap<String, String>();
    
    public void updateExchangeSiteFreeBusyInfo(List<Site> currSiteStatus, Date queryStartTime)
    {        
        //通过会场状态获取某一时间段的会议列表（一个月内）
        updateConfListFromSiteStatus(currSiteStatus);
        
        //移除周期会议的被修改的子会议和它的主会议
        removeNotExistedConf();
        
        //获取30秒内状态发生变化的会议，包含新增，删除，修改
        updateChangedConfListInfo();
        
        //把状态发生变化的会议同步到exchange上
        synchronizationExchangeSiteStatus();
    }
    
    private void updateConfListFromSiteStatus(List<Site> siteStatus)
    {
        if (null == siteStatus)
        {
            return;
        }
        
        confListMap_before.clear();
        for (Entry<String, Conference> entry : confListMap_now.entrySet())
        {
            confListMap_before.put(entry.getKey(), entry.getValue());
        }
        LOGGER.info("the size of confListMap_before is:" + confListMap_before.size());
        
        confListMap_now.clear();
        
        for (Site status : siteStatus)
        {
            for (FreeBusyInfo freeBusyInfo : status.getFreeBusyInfoList())
            {
                String confId = freeBusyInfo.getConfInternalId();
                if (confListMap_now.containsKey(confId))
                {
                    Conference conf = confListMap_now.get(confId);
                    
                    SiteInConference site = new SiteInConference();
                    site.setUri(status.getUri());
                    conf.getSites().add(site);
                }
                else
                {
                    int confLength = DurationUtils.durationStr2int(freeBusyInfo.getTimeRange().getSpan());
                    if (confLength > 0)
                    {
                        Conference conf = new Conference(confId);
                        conf.setName(freeBusyInfo.getConfName());
                        conf.setBeginTime(freeBusyInfo.getTimeRange().getStart());
                        conf.setLength(confLength);
                        
                        List<SiteInConference> sites = new ArrayList<SiteInConference>();
                        
                        SiteInConference site = new SiteInConference();
                        site.setUri(status.getUri());
                        sites.add(site);
                        
                        conf.setSites(sites);
                        
                        confListMap_now.put(conf.getId(), conf);
                    }
                }
            }
        }
        
        List<String> passedConfId = new ArrayList<String>();
        for (Entry<String, Conference> entry : confListMap_now.entrySet())
        {
            Conference conf = entry.getValue();
            Date currentUTCDate = DateUtils.toDate(DateUtils.getCurrentUTCTime());
            long confEndTime = conf.getBeginTime().getTime() + conf.getLength() * 60000L;
            
            //结束时间小于当前时间，证明会议已结束，不必放在会议列表中
            if (confEndTime < currentUTCDate.getTime())
            {
                passedConfId.add(conf.getId());
            }
        }
        
        for (String confId : passedConfId)
        {
            confListMap_now.remove(confId);
        }
        
        LOGGER.info("the size of confListMap_now is:" + confListMap_now.size());
        
    }
    
    private void updateChangedConfListInfo()
    {
        //新增的会议
        for (Entry<String, Conference> entry : confListMap_now.entrySet())
        {
            if (!confListMap_before.containsKey(entry.getKey()))
            {
                changed_confList_add.put(entry.getKey(), entry.getValue());
            }
            else
            {
                String confId = entry.getKey();
                if (isModified(confListMap_now.get(confId), confListMap_before.get(confId)))
                {
                    changed_confList_modify.put(entry.getKey(), entry.getValue());
                }
            }
        }
        
        //删除的会议
        for (Entry<String, Conference> entry : confListMap_before.entrySet())
        {
            if (!confListMap_now.containsKey(entry.getKey()))
            {
                changed_confList_delete.put(entry.getKey(), entry.getValue());
            }
        }
    }
    
    //判断会议是否被修改过
    private boolean isModified(Conference conf1, Conference conf2)
    {
        if (null == conf1 || null == conf2)
        {
            return false;
        }
        
        if (!conf1.getName().equals(conf2.getName()))
        {
            return true;
        }
        else if(conf1.getBeginTime().getTime() != conf2.getBeginTime().getTime())
        {
            return true;
        }
        else if (!conf1.getLength().equals(conf2.getLength()))
        {
            return true;
        }
        else if (conf1.getSites().size() != conf2.getSites().size())
        {
            return true;
        }
        else if (conf1.getSites().size() == conf2.getSites().size())
        {
            int size = conf1.getSites().size();
            for(int i = 0; i < size; i++)
            {
                String siteUri1 = conf1.getSites().get(i).getUri();
                boolean isContains = false;
                for(int j = 0; j < size; j++)
                {
                    String siteUri2 = conf2.getSites().get(j).getUri();
                    if(siteUri1.equals(siteUri2))
                    {
                        isContains = true;
                        break;
                    }
                }
                if(!isContains)
                {
                    return true;
                }
            }
        }
        else
        {
            return false;
        }
        
        return false;
    }
    
    private void synchronizationExchangeSiteStatus()
    {
        //exchange上待增加的会议the size of exchange meeting witch need to add is:
        LOGGER.info("the size of exchange meeting witch need to add is:" + changed_confList_add.size());
        try
        {
            List<String> tempConfIds = new ArrayList<String>();
            for (Entry<String, Conference> entry : changed_confList_add.entrySet())
            {
                Conference conf = entry.getValue();
                
                long halfHourTime = 30 * 60 * 1000L;
                Date startDate = conf.getBeginTime();
                Date endDate = new Date(conf.getBeginTime().getTime() + halfHourTime);
                
                SDKResult<Map<String, Conference>> searchRes = scheduleConf.findExchangeConf(startDate, endDate, false);
                
                if (0 == searchRes.getErrCode() &&
                    null != searchRes.getResult())
                {
                    if(!searchRes.getResult().containsKey(conf.getId()))
                    {
                        Conference conference = tpoaConfMgrConvert.convertTPConf2ExchangeConf(conf);
                        
                        SDKResult<String> result = scheduleConf.scheduleExchangeConf(conference);
                        
                        if (0 == result.getErrCode())
                        {
                            tempConfIds.add(entry.getKey());
                            TPOADataMapping.confIdMapping.put(conf.getId(), result.getResult());
                        }
                    }
                    else
                    {
                        tempConfIds.add(entry.getKey());
                        TPOADataMapping.confIdMapping.put(conf.getId(),
                            searchRes.getResult().get(conf.getId()).getId());
                    }
                }
            }
            
            for(String tempId : tempConfIds)
            {
                changed_confList_add.remove(tempId);
            }
        }
        catch (SDKException e)
        {
            LOGGER.error("add exchange meeting failed", e);
        }

        //exchange上待删除的会议
        LOGGER.info("the size of exchange meeting witch need to delete is:" + changed_confList_delete.size());
        try
        {
            List<String> tempConfIds = new ArrayList<String>();
            for (Entry<String, Conference> entry : changed_confList_delete.entrySet())
            {
                //通过TP会议Id获取关联的exchange会议Id，在南向删除exchange会议
                String exchangeConfId = TPOADataMapping.confIdMapping.get(entry.getKey());
                if (null != exchangeConfId)
                {
                    SDKErrorCode response = scheduleConf.cancelExchangeConf(exchangeConfId);
                    
                    if(0 == response.getErrCode())
                    {
                        tempConfIds.add(entry.getKey());
                    }
                }
            }
            
            for(String tempId : tempConfIds)
            {
                changed_confList_delete.remove(tempId);
            }
        }
        catch (Exception e)
        {
            LOGGER.error("delete exchange meeting failed", e);
        }
        
        //exchange上待修改的会议
        LOGGER.info("the size of exchange meeting witch need to modify is:" + changed_confList_modify.size());
        try
        {
            List<String> tempConfIds = new ArrayList<String>();
            for (Entry<String, Conference> entry : changed_confList_modify.entrySet())
            {
                Conference conf = entry.getValue();
                String exchangeConfId = TPOADataMapping.confIdMapping.get(conf.getId());
                
                if (null != exchangeConfId)
                {
                    Conference conference = tpoaConfMgrConvert.convertTPConf2ExchangeConf(conf);
                    conference.setId(exchangeConfId);

                    SDKResult<String> response = scheduleConf.editExchangeConf(conference);
                    
                    if(0 == response.getErrCode())
                    {
                        tempConfIds.add(entry.getKey());
                    }
                }
            }
            
            for(String tempId : tempConfIds)
            {
                changed_confList_modify.remove(tempId);
            }
        }
        catch (SDKException e)
        {
            LOGGER.error("modify exchange meeting failed", e);
        }
    }
    
    public void restoreInitialValue(Date startDate, int hours)
        throws SDKException
    {
        long hourTime = hours * 3600000L;
        Date endDate = new Date(startDate.getTime() + hourTime);
        
        SDKResult<Map<String, Conference>> searchRes = scheduleConf.findExchangeConf(startDate, endDate, true);
        
        if (0 == searchRes.getErrCode())
        {
            Map<String, Conference> result = searchRes.getResult();
            
            tpoaConfMgrConvert.setInitialValueforSiteSync(result, TPOADataMapping.confIdMapping, confListMap_now);
        }
        
    }
    
    private void removeNotExistedConf()
    {
        //移除周期会议的主会议
        for(Entry<String, Conference> entry : confListMap_now.entrySet())
        {
            String id = entry.getKey();
            String nextId = String.valueOf(Long.parseLong(id) + 1);
            if(confListMap_now.containsKey(nextId))
            {
                if(!isModified(confListMap_now.get(id),
                    confListMap_now.get(nextId)))
                {
                    recurrenceConfParentIds.put(id, id);
                }
            }
        }
        
        //移除周期会议的被修改的子会议
        int numberPerPage = 50;
        String numberPerPageStr = ConfigManager.getInstance().getValue("tpoa_synchAllSitesFreeBusy_numberPerPage");
        if (!StringUtils.isEmpty(numberPerPageStr))
        {
            try
            {
                numberPerPage = Integer.parseInt(numberPerPageStr);
            }
            catch (NumberFormatException e)
            {
                LOGGER.error("NumberFormatException for numberPerPageStr,set default value 50", e);
                numberPerPage = 50;
            }
        }
        int pageNum = 0 == confListMap_now.size()%numberPerPage ?
            confListMap_now.size()/numberPerPage : confListMap_now.size()/numberPerPage+1;
        
        List<String> allConfIds = new ArrayList<String>();
        for(Entry<String, Conference> entry : confListMap_now.entrySet())
        {
            String id = entry.getKey();
            allConfIds.add(id);
        }
        
        for(int i = 0; i < pageNum; i++)
        {
            List<String> confIdsTemp = new ArrayList<String>();
            for(int j = i * numberPerPage;
                j < (i + 1) * numberPerPage && j < allConfIds.size();
                j++)
            {
                confIdsTemp.add(allConfIds.get(j));
            }
            
            SDKResult<List<Conference>> response = null;
            try
            {
                response = Conference.queryConferencesStatus(confIdsTemp);
            }
            catch (SDKException e)
            {
                LOGGER.error("queryConferencesStatus method error", e);
            }
            if(null != response && 
                null != response.getResult())
            {
                for(Conference conf : response.getResult())
                {
                    if(ConfStatus.NOEXIST == conf.getStatus()
                        || ConfStatus.END == conf.getStatus())
                    {
                        confListMap_now.remove(conf.getId());
                        recurrenceConfParentIds.remove(conf.getId());
                    }
                } 
            }
            
            try
            {
                Thread.sleep(2*1000);
            }
            catch (InterruptedException e)
            {
                LOGGER.error("queryConferencesStatus method error", e);
            }
        }
        
        for(String mainconfIds : recurrenceConfParentIds.keySet())
        {
            confListMap_now.remove(mainconfIds);
        }
    }
}
